package com.projectpractice.bean;


import com.projectpractice.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;

/**
 * @author TangLuJie
 * @date 2020/7/5 19:23
 */
public class UserRealm extends AuthorizingRealm {

    @Autowired
    @Lazy//Shiro框架初始化比Spring框架的某些部件早，导致使用@Autowire注入Shiro框架的某些类不能被Spring正确初始化
    private UserService userService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("授权UserRealm--->doGetAuthorizationInfo");
        //获取当前用户权限（在这里与角色绑定一起，三种角色代表三种权限）
        Subject subject = SecurityUtils.getSubject();
        User user= (User) subject.getPrincipal();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        if(user.getRole()==null){//若没有权限则无法登陆（权限与角色绑定）
            return null;
        }
        info.addStringPermission(user.getRole());
        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //设置加密方式
        HashedCredentialsMatcher hashedCredentialsMatcher=new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashIterations(1024);
        hashedCredentialsMatcher.setHashAlgorithmName("MD5");
        this.setCredentialsMatcher(hashedCredentialsMatcher);

        System.out.println("认证UserRealm--->doGetAuthenticationInfo");

        //通过用户名从数据库中获取用户
        UsernamePasswordToken usernamePasswordToken= (UsernamePasswordToken) authenticationToken;
        //记住我功能 controller里面
        //usernamePasswordToken.setRememberMe(true);

        User user = userService.getUserByName(usernamePasswordToken.getUsername());
        if(user==null){
            return null;//抛出异常  UnknownAccountException
        }

        //设置有关信息及盐值
        //1)principal：认证的实体信息，可以是username，也可以是数据库表对应的用户的实体对象
        Object principal = user.getName();
        //2)credentials：密码
        Object credentials = user.getPassword();
        //3)realmName：当前realm对象的name，调用父类的getName()方法即可
        String realmName = getName();
        //4)credentialsSalt盐值
        ByteSource credentialsSalt = ByteSource.Util.bytes(principal);//使用账号作为盐值
        //验证并返回结果
        return new SimpleAuthenticationInfo(user,user.getPassword(),credentialsSalt,realmName);
        //return new SimpleAuthenticationInfo(user.getPassword(),usernamePasswordToken.getPassword());
    }

    public static void main(String[] args) {
        String hashAlgorithmName = "MD5";//加密方式
        Object crd="123";
        Object salt = "kg2";//盐值
        int hashIterations = 1024;//加密1024次
        Object result = new SimpleHash(hashAlgorithmName,crd,salt,hashIterations);
        System.out.println(result);
    }
}
